package com.engine.workflowDesign.biz;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cloudstore.dev.api.util.TextUtil;
import com.engine.workflow.biz.freeNode.FreeNodeBiz;
import com.engine.workflowDesign.entity.*;
import com.engine.workflowDesign.util.DesignUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import sun.misc.BASE64Decoder;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;


import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.List;

public class XmlParserBiz {

    static {
        initNodeColor();
    }

    //创建节点
    public static String CREATE_NODE_STYLE = "ellipse;whiteSpace=wrap;html=1;resizable=0;icons={\"right\":\"icon-workflow-ceshi\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;";
    //审批节点
    public static String APPROVE_NODE_STYLE = "rhombus;whiteSpace=wrap;html=1;fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;";
    //处理节点
    public static String PROCESS_NODE_STYLE = "rounded=0;whiteSpace=wrap;html=1;fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;";
    //归档节点
    public static String DOWN_NODE_STYLE = "ellipse;whiteSpace=wrap;html=1;icons={\"right\":\"icon-workflow-guidang\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;";
    //等待节点
    public static String WAIT_NODE_STYLE = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"center\":\" icon icon-robot icon-robotdfa\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //自动处理节点
    public static String AUTOPROCESS_NODE_STYLE = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"center\": \"icon icon-robot icon-robotRelease-preparation\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //分叉起始点
    public static String SUB_NODE_START = "icons={\"left\":\"icon-workflow-fencha\"};";
    //分叉中间点
    public static String SUB_NODE_MIND = "icons={\"left\":\"icon-workflow-fenchazhongjiandian\"};";
    //分叉合并点
    public static String SUB_NODE_END = "icons={\"left\":\"icon-workflow-hebing\"};";

    //根据前端保存所传格式配置
    //分叉起始点-等待
    public static String SUB_NODE_START_WAIT = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"left\":\"icon-workflow-fencha\",\"center\":\"icon icon-robot icon-robotdfa\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //分叉中间点-等待
    public static String SUB_NODE_MIND_WAIT = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"left\":\"icon-workflow-fenchazhongjiandian\",\"center\": \"icon icon-robot icon-robotdfa\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //分叉合并点-等待
    public static String SUB_NODE_END_WAIT = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"left\":\"icon-workflow-hebing\",\"center\":\"icon icon-robot icon-robotdfa\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //分叉起始点-自动处理
    public static String SUB_NODE_START_AUTOPROCESS = "shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;rotatable=0;icons={\"left\":\"icon-workflow-fencha\",\"center\":\"icon icon-robot icon-robotRelease-preparation\"};fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;fontColor=#345e3a;";
    //分叉中间点-自动处理
    public static String SUB_NODE_MIND_AUTOPROCESS = "shape=hexagon;perimeter=hexagonPerimeter2;rotatable=0;whiteSpace=wrap;html=1;fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;icons={\"left\":\"icon-workflow-fenchazhongjiandian\",\"center\":\"icon icon-robot icon-robotRelease-preparation\"};";
    //分叉合并点-自动处理
    public static String SUB_NODE_END_AUTOPROCESS = "shape=hexagon;perimeter=hexagonPerimeter2;rotatable=0;whiteSpace=wrap;html=1;fillColor=#BFF3C3;strokeColor=#5ABD6B;resizable=0;icons={\"left\":\"icon-workflow-hebing\",\"center\":\"icon icon-robot icon-robotRelease-preparation\"};";

    //路径
    public static String LINK_STYLE = "edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;resizable=0;jettySize=auto;orthogonalLoop=1;";

    //分组
    public static String GROUP_STYLE = "shape=mxgraph.flowchart.process;fillColor=none;dashed=1;strokeColor=#666666;strokeWidth=2;labelPosition=center;verticalLabelPosition=center;align=center;verticalAlign=top;connectable=0;fontWeight:normal;fontSize=12;fontStyle=1;wrap=1;fontColor=#000000;";

    //描述文字
    public static String TEXT_STYLE = "text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;connectable=0;";

    public static boolean colorLoaded = false;
    //已通过节点填充颜色
    public static String PASSED_NODE_FILL_COLOR = "#aae2ff";
    //已通过节点边框颜色
    public static String PASSED_NODE_STROKE_COLOR = "#67bbe2";
    //已通过节点字体颜色
    public static String PASSED_NODE_FONT_COLOR = "#285a78";
    //已通过节点操作者字体颜色
    public static String PASSED_NODE_OPERATOR_FONT_COLOR = "#3c74af";

    //当前节点填充颜色
    public static String NOW_NODE_FILL_COLOR = "#ffe8cc";
    //当前节点边框颜色
    public static String NOW_NODE_STROKE_COLOR = "#f3b474";
    //当前节点字体颜色
    public static String NOW_NODE_FONT_COLOR = "#7c5423";
    //当前节点操作者字体颜色
    public static String NOW_NODE_OPERATOR_FONT_COLOR = "#c4822b";

    //未到达节点填充颜色
    public static String NOARRIVE_NODE_FILL_COLOR = "#bff3c3";
    //未到达节点边框颜色
    public static String NOARRIVE_NODE_STROKE_COLOR = "#71cba1";
    //未到达节点字体颜色
    public static String NOARRIVE_NODE_FONT_COLOR = "#345e3a";
    //未到达节点操作者字体颜色
    public static String NOARRIVE_NODE_OPERATOR_FONT_COLOR = "#429350";

    public static String AUTOPASSED_NODE_STROKE_COLOR = "#da5455";

    //预测节点填充颜色
    public static String FORECAST_NODE_FILL_COLOR = "#98F6EF";
    //预测节点边框颜色
    public static String FORECAST_NODE_STROKE_COLOR = "#1BD1C5";
    //预测节点字体颜色
    public static String FORECAST_NODE_FONT_COLOR = "#087E76";
    //预测节点操作者字体颜色
    public static String FORECAST_NODE_OPERATOR_COLOR = "#087E76";

    //经过的出口颜色
    public static String PASSED_LINK_COLOR = "#da5455";
    //预测的出口颜色
    public static String FORECAST_LINK_COLOR = "#1BD1C5";
    //未经过的出口颜色
    public static String NOPASSED_LINK_COLOR = "#8c8c8c";

    /** XML对象 **/
    public static final String XML_ElEMENT_MXGRAPHMODEL = "mxGraphModel";
    public static final String XML_ELEMENT_ROOT = "root";
    public static final String XML_ELEMENT_MX_CELL = "mxCell";
    public static final String XML_ELEMENT_MX_GEOMETRY = "mxGeometry";
    public static final String XML_ELEMENT_ARRAY = "Array";
    public static final String XML_ELEMENT_MX_POINT = "mxPoint";

    public static final String XML_ATTRIBUTE_ID = "id";
    public static final String XML_ATTRIBUTE_FORMID = "formId";
    public static final String XML_ATTRIBUTE_ISBILL = "isBill";

    public static final String XML_ATTRIBUTE_GRID = "grid";
    public static final String XML_ATTRIBUTE_GRIDSIZE = "gridSize";
    public static final String XML_ATTRIBUTE_GUIDES = "guides";
    public static final String XML_ATTRIBUTE_TOOLTIPS = "tooltips";
    public static final String XML_ATTRIBUTE_CONNECT = "connect";
    public static final String XML_ATTRIBUTE_ARROWS = "arrows";
    public static final String XML_ATTRIBUTE_FOLD = "fold";
    public static final String XML_ATTRIBUTE_PAGE = "page";
    public static final String XML_ATTRIBUTE_PAGESCALE = "pageScale";
    public static final String XML_ATTRIBUTE_PAGEWIDTH = "pageWidth";
    public static final String XML_ATTRIBUTE_PAGEHEIGHT = "pageHeight";
    public static final String XML_ATTRIBUTE_BACKGROUND = "background";
    public static final String XML_ATTRIBUTE_VERTEX = "vertex";
    public static final String XML_ATTRIBUTE_PARENT = "parent";
    public static final String XML_ATTRIBUTE_WIDTH = "width";
    public static final String XML_ATTRIBUTE_HEIGHT = "height";
    public static final String XML_ATTRIBUTE_AS = "as";
    public static final String XML_ATTRIBUTE_RELATIVE = "relative";
    public static final String XML_ATTRIBUTE_ORDER = "order";

    /** 节点属性 **/
    public static final String XML_ATTRIBUTE_NODETYPE = "nodeType";                    //节点类型
    public static final String XML_ATTRIBUTE_NODEID = "nodeId";                        //节点id
    public static final String XML_ATTRIBUTE_VALUE = "value";                          //节点名称
    public static final String XML_ATTRIBUTE_NODEATTRIBUTE = "nodeAttriBute";          //节点属性
    public static final String XML_ATTRIBUTE_PASSBRANCHNUM = "passBranchNum";          //通过的分支数量
    public static final String XML_ATTRIBUTE_PROPORTMERGE = "proportMerge";            //通过的分支比例
    public static final String XML_ATTRIBUTE_TARGETBRANCHVALUE = "targetBranchValue";  //通过的分支数量
    public static final String XML_ATTRIBUTE_OPERATORNAMESTR = "operatorNameStr";      //操作者名称
    public static final String XML_ATTRIBUTE_CURRENTNODE = "isCurrentNode";            //是否流程当前节点
    public static final String XML_ATTRIBUTE_ISFORECASTNODE = "isForecastNode";        //是否流程预测节点

    public final int OLDNODE_APPEND_X = 30;//老数据的节点X偏移量
    public final int OLDNODE_APPEND_Y = 30;//老数据的几点Y偏移量

    /** 出口属性 **/
    public static final String XML_ATTRIBUTE_EDGE = "edge";
    public static final String XML_ATTRIBUTE_LINKID = "linkId";
    public static final String XML_ATTRIBUTE_SOURCE = "source";//开始节点mxCell标签的id
    public static final String XML_ATTRIBUTE_TARGET = "target";//结束节点mxCell标签的id
    public static final String XML_ATTRIBUTE_TEXT = "value";//路径名称
    public static final String XML_ATTRIBUTE_STYLE = "style";
    public static final String XML_ATTRIBUTE_EXITINFO = "exitInfo";//出口提示信息
    public static final String XML_ATTRIBUTE_ISBUILDCODE = "isBuildCode";//是否生成编号
    public static final String XML_ATTRIBUTE_ISREJECT = "isreject";//是否退回出口
    public static final String XML_ATTRIBUTE_LINKCONDITIONINFO = "linkConditionInfo";//出口条件

    /** 分组 **/
    public static final String XML_ATTRIBUTE_ISGROUPAREA = "isGroupArea";//是否分组

    /**
     * 文字说明
     **/
    public static final String XML_ATTRIBUTE_ISHELPFULTEXT = "isHelpfulText";//是否文字说明
    public static final String XML_ATTRIBUTE_ISEDITTING = "isEditing";

    public static final String XML_ATTRIBUTE_X = "x";
    public static final String XML_ATTRIBUTE_Y = "y";

    private User user;
    private String remoteAddr;

    private String delNodeIds = "";
    private String delGroupIds = "";
    private String delStepIds = "";
    private String groupsJsonStr = "";

    private int requestId;

    //前台表单调用
    private boolean isFromWfForm;

    //后台只读调用
    private boolean backstageReadOnly;

    //是否显示预测节点
    private boolean showForecastNode;

    public XmlParserBiz(User user, String remoteAddr) {
        this.user = user;
        this.remoteAddr = Util.null2String(remoteAddr);
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getRemoteAddr() {
        return remoteAddr;
    }

    public void setRemoteAddr(String remoteAddr) {
        this.remoteAddr = remoteAddr;
    }

    public String getDelNodeIds() {
        return delNodeIds;
    }

    public void setDelNodeIds(String delNodeIds) {
        this.delNodeIds = delNodeIds;
    }

    public String getDelGroupIds() {
        return delGroupIds;
    }

    public void setDelGroupIds(String delGroupIds) {
        this.delGroupIds = delGroupIds;
    }

    public String getDelStepIds() {
        return delStepIds;
    }

    public void setDelStepIds(String delStepIds) {
        this.delStepIds = delStepIds;
    }

    public String getGroupsJsonStr() {
        return groupsJsonStr;
    }

    public void setGroupsJsonStr(String groupsJsonStr) {
        this.groupsJsonStr = groupsJsonStr;
    }

    public int getRequestId() {
        return requestId;
    }

    public void setRequestId(int requestId) {
        this.requestId = requestId;
    }

    public boolean isFromWfForm() {
        return isFromWfForm;
    }

    public void setFromWfForm(boolean fromWfForm) {
        isFromWfForm = fromWfForm;
    }

    public boolean isBackstageReadOnly() {
        return backstageReadOnly;
    }

    public void setBackstageReadOnly(boolean backstageReadOnly) {
        this.backstageReadOnly = backstageReadOnly;
    }

    public boolean isShowForecastNode() {
        return showForecastNode;
    }

    public void setShowForecastNode(boolean showForecastNode) {
        this.showForecastNode = showForecastNode;
    }

    public boolean saveLayout(int workflowId, String xmlContent) {
        LayoutDataBiz layoutDataBiz = new LayoutDataBiz(user);
        Workflow workflow = this.parserXmlToWorkflow(workflowId, xmlContent);
        return layoutDataBiz.writeWorkflowToDB(workflow, remoteAddr, delGroupIds, delNodeIds, delStepIds);
    }

    public static Map<String, Object> getNodeColorInfo() {
        Map<String, Object> flowChartColorInfo = new HashMap<>();

        XmlParserBiz.initNodeColor();

        flowChartColorInfo.put("PASSED_NODE_FILL_COLOR", XmlParserBiz.PASSED_NODE_FILL_COLOR);
        flowChartColorInfo.put("PASSED_NODE_STROKE_COLOR", XmlParserBiz.PASSED_NODE_STROKE_COLOR);
        flowChartColorInfo.put("PASSED_NODE_FONT_COLOR", XmlParserBiz.PASSED_NODE_FONT_COLOR);
        flowChartColorInfo.put("PASSED_NODE_OPERATOR_FONT_COLOR", XmlParserBiz.PASSED_NODE_OPERATOR_FONT_COLOR);

        flowChartColorInfo.put("NOW_NODE_FILL_COLOR", XmlParserBiz.NOW_NODE_FILL_COLOR);
        flowChartColorInfo.put("NOW_NODE_STROKE_COLOR", XmlParserBiz.NOW_NODE_STROKE_COLOR);
        flowChartColorInfo.put("NOW_NODE_FONT_COLOR", XmlParserBiz.NOW_NODE_FONT_COLOR);
        flowChartColorInfo.put("NOW_NODE_OPERATOR_FONT_COLOR", XmlParserBiz.NOW_NODE_OPERATOR_FONT_COLOR);

        flowChartColorInfo.put("NOARRIVE_NODE_FILL_COLOR", XmlParserBiz.NOARRIVE_NODE_FILL_COLOR);
        flowChartColorInfo.put("NOARRIVE_NODE_STROKE_COLOR", XmlParserBiz.NOARRIVE_NODE_STROKE_COLOR);
        flowChartColorInfo.put("NOARRIVE_NODE_FONT_COLOR", XmlParserBiz.NOARRIVE_NODE_FONT_COLOR);
        flowChartColorInfo.put("NOARRIVE_NODE_OPERATOR_FONT_COLOR", XmlParserBiz.NOARRIVE_NODE_OPERATOR_FONT_COLOR);

        flowChartColorInfo.put("AUTOPASSED_NODE_STROKE_COLOR", XmlParserBiz.AUTOPASSED_NODE_STROKE_COLOR);
        flowChartColorInfo.put("FORECAST_NODE_FILL_COLOR", XmlParserBiz.FORECAST_NODE_FILL_COLOR);
        flowChartColorInfo.put("FORECAST_NODE_STROKE_COLOR", XmlParserBiz.FORECAST_NODE_STROKE_COLOR);
        flowChartColorInfo.put("FORECAST_NODE_FONT_COLOR", XmlParserBiz.FORECAST_NODE_FONT_COLOR);
        flowChartColorInfo.put("FORECAST_NODE_OPERATOR_COLOR", XmlParserBiz.FORECAST_NODE_OPERATOR_COLOR);

        flowChartColorInfo.put("PASSED_LINK_COLOR", XmlParserBiz.PASSED_LINK_COLOR);
        flowChartColorInfo.put("FORECAST_LINK_COLOR", XmlParserBiz.FORECAST_LINK_COLOR);
        flowChartColorInfo.put("NOPASSED_LINK_COLOR", XmlParserBiz.NOPASSED_LINK_COLOR);

        return flowChartColorInfo;
    }

    public static void initNodeColor() {

        //颜色加载过，则不再从数据库中加载
        if (colorLoaded) {
            return;
        }

        RecordSet rs = new RecordSet();
        rs.executeQuery("select * from workflow_designcolors");
        if (rs.next()) {
            PASSED_NODE_FILL_COLOR = rs.getString("PASSED_NODE_FILL_COLOR");
            PASSED_NODE_STROKE_COLOR = rs.getString("PASSED_NODE_STROKE_COLOR");
            PASSED_NODE_FONT_COLOR = rs.getString("PASSED_NODE_FONT_COLOR");
            PASSED_NODE_OPERATOR_FONT_COLOR = rs.getString("PASSED_NODE_OPERATOR_FONT");

            NOW_NODE_FILL_COLOR = rs.getString("NOW_NODE_FILL_COLOR");
            NOW_NODE_STROKE_COLOR = rs.getString("NOW_NODE_STROKE_COLOR");
            NOW_NODE_FONT_COLOR = rs.getString("NOW_NODE_FONT_COLOR");
            NOW_NODE_OPERATOR_FONT_COLOR = rs.getString("NOW_NODE_OPERATOR_FONT_COLOR");

            NOARRIVE_NODE_FILL_COLOR = rs.getString("NOARRIVE_NODE_FILL_COLOR");
            NOARRIVE_NODE_STROKE_COLOR = rs.getString("NOARRIVE_NODE_STROKE_COLOR");
            NOARRIVE_NODE_FONT_COLOR = rs.getString("NOARRIVE_NODE_FONT_COLOR");
            NOARRIVE_NODE_OPERATOR_FONT_COLOR = rs.getString("NOARRIVE_NODE_OPERATOR_FONT");

            AUTOPASSED_NODE_STROKE_COLOR = rs.getString("AUTOPASSED_NODE_STROKE_COLOR");

            FORECAST_NODE_FILL_COLOR = rs.getString("FORECAST_NODE_FILL_COLOR");
            FORECAST_NODE_STROKE_COLOR = rs.getString("FORECAST_NODE_STROKE_COLOR");
            FORECAST_NODE_FONT_COLOR = rs.getString("FORECAST_NODE_FONT_COLOR");
            FORECAST_NODE_OPERATOR_COLOR = rs.getString("FORECAST_NODE_OPERATOR_COLOR");

            PASSED_LINK_COLOR = rs.getString("PASSED_LINK_COLOR");
            FORECAST_LINK_COLOR = rs.getString("FORECAST_LINK_COLOR");
            NOPASSED_LINK_COLOR = rs.getString("NOPASSED_LINK_COLOR");
            colorLoaded = true;
        }
    }

    public Map<String, Object> parserWorkflowToXml(Workflow workflow) {

        Map<String, Object> xmlInfo = new HashMap<>();
        boolean isE9Save = false;//是否新版流程图保存（只要节点和出口存在style，则视为新版流程图保存)

        /**构建XML文档对象*/
        Document doc = null;
        doc = DocumentHelper.createDocument();

        /**创建mxGraphModel节点*/
        Element mxGraphModelElement = doc.addElement(XML_ElEMENT_MXGRAPHMODEL);
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_GRID, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_GRIDSIZE, "10");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_GUIDES, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_TOOLTIPS, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_CONNECT, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_ARROWS, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_FOLD, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_PAGE, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_PAGESCALE, "1");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_PAGEWIDTH, "1430");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_PAGEHEIGHT, "516");
        mxGraphModelElement.addAttribute(XML_ATTRIBUTE_BACKGROUND, "#ffffff");

        /**创建root节点及固定的mxCell节点**/
        Element root = mxGraphModelElement.addElement(XML_ELEMENT_ROOT);
        Element mxCell1 = root.addElement(XML_ELEMENT_MX_CELL);
        mxCell1.addAttribute(XML_ATTRIBUTE_ID, "0");
        mxCell1.addAttribute(XML_ATTRIBUTE_VERTEX, "1");


        Element mxCell2 = root.addElement(XML_ELEMENT_MX_CELL);
        mxCell2.addAttribute(XML_ATTRIBUTE_ID, "1");
        mxCell2.addAttribute(XML_ATTRIBUTE_VERTEX, "1");
        mxCell2.addAttribute(XML_ATTRIBUTE_PARENT, "0");

        //分叉合并节点的 通过指定分支合并 属性
        Map<Integer, String> nodeTargetBranchValueMap = new HashMap<>();


        Map<String, Map<String, Object>> formNodeInfo = new HashMap<>();//表单进来时，根据requestid获取的节点信息
        Map<String, Map<String, Object>> formLinkInfo = new HashMap<>();//表单进来时，根据requestid获取的出口信息

        if (isFromWfForm) {//前台表单进来
            initNodeColor();
            RequestDisplayInfoBiz reqDisplayInfo = null;
            Map reqDisBean = null;
            reqDisplayInfo = new RequestDisplayInfoBiz(String.valueOf(workflow.getId()), String.valueOf(this.requestId));
            reqDisplayInfo.setUser(user);
            reqDisplayInfo.setShowForecastNode(showForecastNode);
            try {
                reqDisBean = reqDisplayInfo.getReqDisInfo();
                List nodeDisInfo = (List) reqDisBean.get("nodeinfo");
                List nodeLinkLineInfo = (List) reqDisBean.get("lineinfo");
                for(Iterator it = nodeDisInfo.iterator(); it.hasNext();) {
                    Map<String, Object> nodeBean = (Map) it.next();
                    nodeBean.put("viewers", parseResourceInfo((List<String>)nodeBean.get("nodeViewNameList")));
                    nodeBean.put("operators", parseResourceInfo((List<String>)nodeBean.get("nodeOperatorNameList")));
                    nodeBean.put("notOperators", parseResourceInfo((List<String>)nodeBean.get("nodeNotOperatorNameList")));
                    formNodeInfo.put(nodeBean.get("nodeid") + "", nodeBean);
                }
                for(Iterator it = nodeLinkLineInfo.iterator(); it.hasNext();) {
                    Map<String, Object> linkBean = (Map) it.next();
                    formLinkInfo.put(linkBean.get("linkid") + "", linkBean);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        int minXpos = 0;
        int minYpos = 0;

        Map<Integer, WorkflowNode> nodeMap = new HashMap<>();
        for (int i = 0; i < workflow.nodes.size(); i++) {
            WorkflowNode workflowNode = (WorkflowNode)workflow.nodes.get(i);
            nodeMap.put(workflowNode.getId(), workflowNode);

            //记录为负数的节点坐标，在后面整体增加坐标处理
            if (workflowNode.x < minXpos) {
                minXpos = workflowNode.x;
            }

            if (workflowNode.y < minYpos) {
                minYpos = workflowNode.y;
            }
        }

        boolean isFreeWf = FreeNodeBiz.isFreeFlow(workflow.id);
        boolean hasFreeNode = requestId > 0 ? FreeNodeBiz.hasFreeNode(requestId) : false;

        if(!(isFreeWf && hasFreeNode)) {
            //创建所有路径
            for (int i = 0; i < workflow.lines.size(); i++) {
                WorkflowLine workflowLine = (WorkflowLine) workflow.lines.get(i);

                if ("1".equals(workflowLine.getIsMustpass())) {
                    String branchValue = nodeTargetBranchValueMap.get(workflowLine.toNodeId);
                    if (branchValue != null && branchValue.length() > 0) {
                        nodeTargetBranchValueMap.put(workflowLine.toNodeId, branchValue + ",link_" + workflowLine.getId());
                    } else {
                        nodeTargetBranchValueMap.put(workflowLine.toNodeId, "link_" + workflowLine.getId());
                    }
                }

                Element line = root.addElement(XML_ELEMENT_MX_CELL);
                line.addAttribute(XML_ATTRIBUTE_EDGE, "1");
                line.addAttribute(XML_ATTRIBUTE_LINKID, workflowLine.getId() + "");
                line.addAttribute(XML_ATTRIBUTE_ID, "link_" + workflowLine.getId());
                line.addAttribute(XML_ATTRIBUTE_PARENT, "1");
                line.addAttribute(XML_ATTRIBUTE_TEXT, workflowLine.getLineName());
                line.addAttribute(XML_ATTRIBUTE_SOURCE, "node_" + workflowLine.fromNodeId);
                line.addAttribute(XML_ATTRIBUTE_TARGET, "node_" + workflowLine.toNodeId);
                line.addAttribute(XML_ATTRIBUTE_ISREJECT, workflowLine.getIsReject());
                line.addAttribute(XML_ATTRIBUTE_EXITINFO, workflowLine.getRemindMsg());

                String style = LINK_STYLE;
                String newPointsStr = "";
                boolean isOldData = false;//是否为E9新版流程图之前的老数据
                if (!"".equals(workflowLine.getStyle())) {//有style属性的为E9新数据
                    newPointsStr = workflowLine.getE9Points();
                    style = workflowLine.getStyle();
                    isE9Save = true;
                } else {//没有style属性的为E8老数据
                    //将路径 出口和入口的连接方向加入到style中
                    this.filterLinkPoint(workflowLine);
                    newPointsStr = workflowLine.getNewPoints();
                    style = appendDirectionStyle(style, workflowLine, nodeMap);
                    isOldData = true;
                }


                if (isFromWfForm) {//表单进来，改变路径的颜色
                    Map <String, Object> linkBean = formLinkInfo.get(workflowLine.getId() + "");
                    if (linkBean != null) {
                        String isPass = Util.null2String(linkBean.get("ispass"));
                        String isForecast = Util.null2String(linkBean.get("isForecast"));
                        if ("true".equals(isPass)) {//通过的路径线条为红色
                            style = changeColor(style, "strokeColor", PASSED_LINK_COLOR);
                        }else if("true".equals(isForecast)) {
                            style = changeColor(style, "strokeColor", FORECAST_LINK_COLOR);
                        } else {
                            style = changeColor(style, "strokeColor", NOPASSED_LINK_COLOR);
                        }
                    }
                }
                line.addAttribute(XML_ATTRIBUTE_STYLE, style);

                Element mxGeometry = line.addElement(XML_ELEMENT_MX_GEOMETRY);
                mxGeometry.addAttribute(XML_ATTRIBUTE_AS, "geometry");
                mxGeometry.addAttribute(XML_ATTRIBUTE_RELATIVE, "1");

                if (newPointsStr != null && newPointsStr.length() != 0) {
                    String[] newPoints = newPointsStr.split(",");
                    Element array = mxGeometry.addElement(XML_ELEMENT_ARRAY);
                    array.addAttribute(XML_ATTRIBUTE_AS, "points");
                    for (int n = 0; n <= newPoints.length - 2; n = n + 2) {
                        double xPoint = Util.getDoubleValue(newPoints[n]);
                        double yPoint = Util.getDoubleValue(newPoints[n + 1]);
                        if (isOldData) {//老数据连接点xy坐标加20， 和节点同步
                            xPoint += 20;
                            yPoint += 20;
                        }

                        if (minXpos < 0) {
                            xPoint += Math.abs(minXpos) + 200;
                        }

                        if (minYpos < 0) {
                            yPoint += Math.abs(minYpos) + 200;
                        }

                        Element pointElement = array.addElement(XML_ELEMENT_MX_POINT);
                        pointElement.addAttribute(XML_ATTRIBUTE_X, xPoint + "");
                        pointElement.addAttribute(XML_ATTRIBUTE_Y, yPoint + "");
                    }
                }
            }
        }

        List<Integer> autoPassedNodeIds = getAutoPassedNodeIds(requestId);

        /**创建所有流程节点*/
        for (int i = 0; i < workflow.nodes.size(); i++) {
            WorkflowNode workflowNode = (WorkflowNode) workflow.nodes.get(i);

            Element nodeCell = root.addElement(XML_ELEMENT_MX_CELL);

            nodeCell.addAttribute(XML_ATTRIBUTE_ID, "node_" + workflowNode.getId());
            nodeCell.addAttribute(XML_ATTRIBUTE_NODEID, "" + workflowNode.getId());
            nodeCell.addAttribute(XML_ATTRIBUTE_VALUE, workflowNode.getName());
            nodeCell.addAttribute(XML_ATTRIBUTE_VERTEX, "1");
            nodeCell.addAttribute(XML_ATTRIBUTE_PARENT, "1");
            nodeCell.addAttribute(XML_ATTRIBUTE_NODETYPE, workflowNode.getNodeType());
            nodeCell.addAttribute(XML_ATTRIBUTE_NODEATTRIBUTE, workflowNode.getNodeAttribute());
            if ("3".equals(workflowNode.getNodeAttribute())) {
                nodeCell.addAttribute(XML_ATTRIBUTE_PASSBRANCHNUM, Util.null2String(workflowNode.getPassnum()));
            } else if("4".equals(workflowNode.getNodeAttribute())){
                nodeCell.addAttribute(XML_ATTRIBUTE_TARGETBRANCHVALUE, nodeTargetBranchValueMap.get(workflowNode.getId()));
            } else if ("5".equals(workflowNode.getNodeAttribute())) {
                nodeCell.addAttribute(XML_ATTRIBUTE_PROPORTMERGE, Util.null2String(workflowNode.getPassnum()));
            }
            String style = "";
            if(!"".equals(workflowNode.getStyle())) {
//                style = workflowNode.getStyle().replace("shape=mxgraph.flowchart.terminator;", "ellipse;");//对于已产生的新数据，修正创建节点和归档节点的形状
                isE9Save = true;
            } else {
                //兼容老数据
                workflowNode.x += OLDNODE_APPEND_X;//老数据x/y整体下移
                workflowNode.y += OLDNODE_APPEND_Y;
            }
            switch (workflowNode.getNodeType()) {
                case "0" : {
                    style = CREATE_NODE_STYLE;
                    break;
                }
                case "1" : {
                    style = APPROVE_NODE_STYLE;
                    break;
                }
                case "2" : {
                    style = PROCESS_NODE_STYLE;
                    break;
                }
                case "3" : {
                    style = DOWN_NODE_STYLE;
                    break;
                }
            }

            //机器人节点统一取后端配置
            switch (workflowNode.getNodeType()) {
                case "5" : {
                    style = WAIT_NODE_STYLE;
                    break;
                }
                case "6" : {
                    style = AUTOPROCESS_NODE_STYLE;
                    break;
                }
            }

            if(!"0".equals(workflowNode.getNodeAttribute()) && !"".equals(workflowNode.getNodeAttribute())) {
                switch (workflowNode.getNodeAttribute()) {
                    case "1" : {
                        if("5".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_START_WAIT;
                        }else if("6".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_START_AUTOPROCESS;
                        }else{
                            style += SUB_NODE_START;
                        }
                        break;
                    }
                    case "2" : {
                        if("5".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_MIND_WAIT;
                        }else if("6".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_MIND_AUTOPROCESS;
                        }else{
                            style += SUB_NODE_MIND;
                        }
                        break;
                    }
                    default : {
                        if("5".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_END_WAIT;
                        }else if("6".equals(workflowNode.getNodeType())){
                            style = SUB_NODE_END_AUTOPROCESS;
                        }else{
                            style += SUB_NODE_END;
                        }
                        break;
                    }
                }
            }

            if (isFromWfForm) {//表单进来，改变节点的颜色
                Map<String, Object> nodeBean = formNodeInfo.get(workflowNode.getId() + "");
                if (nodeBean != null) {
                    int status = Util.getIntValue(Util.null2String(nodeBean.get("nodeType")), 0);// 节点状态 0:已通过1:当前 2:其它,3:预测
                    String fillColorStr = "";
                    String strokeColor = "";
                    String fontColor = "";
                    String operatorFontColor = "";

                    //是否是多人签批节点
                    boolean isMoreOperator = false;
                    List<String> allOperator = new ArrayList<>(100);

                    //已查看
                    List<Map<String,Object>> viewers = (List<Map<String, Object>>) nodeBean.get("viewers");
                    //已操作
                    List<Map<String,Object>> operators = (List<Map<String, Object>>) nodeBean.get("operators");
                    //未操作
                    List<Map<String,Object>> notOperators = (List<Map<String, Object>>) nodeBean.get("notOperators");

                    for(Map<String,Object> map : viewers){
                        String type = Util.null2String(map.get("type"));
                        String id = Util.null2String(map.get("id"));
                        if("0".equals(type) && !allOperator.contains(id)){
                            allOperator.add(id);
                        }
                    }

                    for(Map<String,Object> map : operators){
                        String type = Util.null2String(map.get("type"));
                        String id = Util.null2String(map.get("id"));
                        if("0".equals(type) && !allOperator.contains(id)){
                            allOperator.add(id);
                        }
                    }

                    for(Map<String,Object> map : notOperators){
                        String type = Util.null2String(map.get("type"));
                        String id = Util.null2String(map.get("id"));
                        if("0".equals(type) && !allOperator.contains(id)){
                            allOperator.add(id);
                        }
                    }
                    if(allOperator.size() > 1){
                        isMoreOperator = true;
                    }



                    if(status == 1) {
                        fillColorStr = NOW_NODE_FILL_COLOR;
                        strokeColor = NOW_NODE_STROKE_COLOR;
                        fontColor = NOW_NODE_FONT_COLOR;
                        operatorFontColor = NOW_NODE_OPERATOR_FONT_COLOR;
                    }  else if(status == 0){
                        fillColorStr = PASSED_NODE_FILL_COLOR;
                        strokeColor = PASSED_NODE_STROKE_COLOR;
                        fontColor = PASSED_NODE_FONT_COLOR;
                        operatorFontColor = PASSED_NODE_OPERATOR_FONT_COLOR;
                    } else if(autoPassedNodeIds.indexOf(workflowNode.getId()) > -1) {
                        //自动跳过的节点
                        strokeColor = AUTOPASSED_NODE_STROKE_COLOR;
                        fillColorStr = PASSED_NODE_FILL_COLOR;
                        fontColor = PASSED_NODE_FONT_COLOR;
                        operatorFontColor = PASSED_NODE_OPERATOR_FONT_COLOR;
                    } else if (status == 2) {
                        fillColorStr = NOARRIVE_NODE_FILL_COLOR;
                        strokeColor = NOARRIVE_NODE_STROKE_COLOR;
                        fontColor = NOARRIVE_NODE_FONT_COLOR;
                        operatorFontColor = NOARRIVE_NODE_OPERATOR_FONT_COLOR;
                    } else if (status == 3) {
                        fillColorStr = FORECAST_NODE_FILL_COLOR;
                        strokeColor = FORECAST_NODE_STROKE_COLOR;
                        fontColor = FORECAST_NODE_FONT_COLOR;
                        operatorFontColor = FORECAST_NODE_OPERATOR_COLOR;
                        //添加预测节点标识
                        nodeCell.addAttribute(XML_ATTRIBUTE_ISFORECASTNODE, "1");
                    }
                    style = changeColor(style, "strokeColor", strokeColor);
                    style = changeColor(style, "fillColor", fillColorStr);
                    style = changeColor(style, "fontColor", fontColor);
                    style = changeColor(style, "operatorFontColor", operatorFontColor);

                    String operatorStr = Util.null2String(nodeBean.get("nodeOperatorName"));
                    if (operatorStr != null && operatorStr.length() > 0) {
                        String[] operatorStrArr = operatorStr.split("->");
                        if (operatorStrArr.length == 2) {//存在代理
                            operatorStr = operatorStrArr[0].substring(operatorStrArr[0].lastIndexOf("#_") + 2) + " -> " + operatorStrArr[1].substring(operatorStrArr[1].lastIndexOf("#_") + 2);
                        } else {
                            operatorStr = operatorStr.substring(operatorStr.lastIndexOf("#_") + 2);
                        }
                    }
                    if(status == 1) {//流程当前节点
                        nodeCell.addAttribute(XML_ATTRIBUTE_CURRENTNODE, "1");
                    }
                    if(isMoreOperator){
                        nodeCell.addAttribute(XML_ATTRIBUTE_OPERATORNAMESTR, "...");
                    }else{
                        nodeCell.addAttribute(XML_ATTRIBUTE_OPERATORNAMESTR, operatorStr);

                    }
                }
            }


            if (!isFromWfForm) {
                style = filterStyle(style, workflowNode);
            }

            nodeCell.addAttribute(XML_ATTRIBUTE_STYLE, style);

            Element mxGeometry = nodeCell.addElement(XML_ELEMENT_MX_GEOMETRY);


            if (minXpos < 0) {
                workflowNode.x += Math.abs(minXpos) + 200;
            }

            if (minYpos < 0) {
                workflowNode.y += Math.abs(minYpos) + 200;
            }

            mxGeometry.addAttribute(XML_ATTRIBUTE_X, workflowNode.x + "");

            mxGeometry.addAttribute(XML_ATTRIBUTE_Y, workflowNode.y + "");
            mxGeometry.addAttribute(XML_ATTRIBUTE_WIDTH, workflowNode.getWidth()+"");
            mxGeometry.addAttribute(XML_ATTRIBUTE_HEIGHT, workflowNode.getHeight()+"");
            mxGeometry.addAttribute(XML_ATTRIBUTE_AS, "geometry");
        }

        for (int i = 0; i < workflow.getGroups().size(); i++) {
            WorkflowGroup workflowGroup = (WorkflowGroup)workflow.getGroups().get(i);

            if (!isE9Save) {//如果是老数据， 需要和节点一样加上x.y坐标偏移量
                workflowGroup.setX(workflowGroup.getX() + OLDNODE_APPEND_X);
                workflowGroup.setY(workflowGroup.getY() + OLDNODE_APPEND_Y);
            }

            Double direction = workflowGroup.getDirection();
            if (direction == 0) {//非横纵向分组
                Element group = root.addElement(XML_ELEMENT_MX_CELL);
                group.addAttribute(XML_ATTRIBUTE_ID, "group_" + workflowGroup.getId());
                group.addAttribute(XML_ATTRIBUTE_VALUE, (isFromWfForm || isBackstageReadOnly()) ? workflowGroup.getGroupname() : TextUtil.toBase64ForMultilang(workflowGroup.getGroupname()));
                group.addAttribute(XML_ATTRIBUTE_STYLE, GROUP_STYLE);
                group.addAttribute(XML_ATTRIBUTE_VERTEX, "1");
                group.addAttribute(XML_ATTRIBUTE_ISGROUPAREA, "1");
                group.addAttribute(XML_ATTRIBUTE_PARENT, "1");

                Element geometry = group.addElement(XML_ELEMENT_MX_GEOMETRY);
                geometry.addAttribute(XML_ATTRIBUTE_AS, "geometry");
                geometry.addAttribute(XML_ATTRIBUTE_X, workflowGroup.getX()+"");
                geometry.addAttribute(XML_ATTRIBUTE_Y, workflowGroup.getY()+"");
                geometry.addAttribute(XML_ATTRIBUTE_WIDTH, workflowGroup.getWidth()+"");
                geometry.addAttribute(XML_ATTRIBUTE_HEIGHT, workflowGroup.getHeight()+"");
            }
        }

        for (int i = 0; i < workflow.getTextInfos().size(); i++) {
            TextInfo textInfo = workflow.getTextInfos().get(i);
            Element textElement = root.addElement(XML_ELEMENT_MX_CELL);
            textElement.addAttribute(XML_ATTRIBUTE_ID, "text_" + textInfo.getId());
            textElement.addAttribute(XML_ATTRIBUTE_VALUE, textInfo.getTextValue());
            textElement.addAttribute(XML_ATTRIBUTE_STYLE, TEXT_STYLE);
            textElement.addAttribute(XML_ATTRIBUTE_VERTEX, "1");
            textElement.addAttribute(XML_ATTRIBUTE_ISHELPFULTEXT, "1");
            textElement.addAttribute(XML_ATTRIBUTE_PARENT, "1");
            textElement.addAttribute(XML_ATTRIBUTE_ISEDITTING, "0");

            Element geometry = textElement.addElement(XML_ELEMENT_MX_GEOMETRY);
            geometry.addAttribute(XML_ATTRIBUTE_AS, "geometry");
            geometry.addAttribute(XML_ATTRIBUTE_X, textInfo.getxPoint()+"");
            geometry.addAttribute(XML_ATTRIBUTE_Y, textInfo.getyPoint()+"");
            geometry.addAttribute(XML_ATTRIBUTE_WIDTH, textInfo.getWidth()+"");
            geometry.addAttribute(XML_ATTRIBUTE_HEIGHT, textInfo.getHeight()+"");

        }

        /** 获取XML文件内容*/
        String xmlContent="";
        xmlContent = doc.asXML();
        try {
            xmlContent = Util.replace(xmlContent, "\n", "", 0);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        xmlInfo.put("xml", xmlContent);
        xmlInfo.put("isE9Save", isE9Save);
        if (isFromWfForm) {
            xmlInfo.put("nodeInfo", formNodeInfo);
        }

        return xmlInfo;
    }

    /**
     * 将xml转化成workflow对象
     * @param xmlContent
     * @return
     */
    public Workflow parserXmlToWorkflow(int workflowId, String xmlContent) {



        Hashtable tmpList = new Hashtable();
        /**创建工作流*/
        Workflow workflow = new Workflow();
        workflow.setId(workflowId);

        /**构建XML文件*/
        SAXReader reader = new SAXReader();
        Document doc = null;
        try {
            InputStream in = null;
            in = new ByteArrayInputStream(xmlContent.getBytes("UTF8"));
            doc = reader.read(in);
            /**获取最外层节点*/
            Element graphModelElemet = doc.getRootElement();

            /**获取root节点**/
            Element rootElement = graphModelElemet.element(XML_ELEMENT_ROOT);

            /**获取所有xmCell节点**/
            List<Element> mxCells = rootElement.elements(XML_ELEMENT_MX_CELL);

            // TD100149 begin -- 根据workflowid获取已有的节点id和节点顺序的映射
            RecordSet rs = new RecordSet();
            Map<String, String> nodeorderMap = new HashMap<String, String>();
            rs.executeQuery("select nodeid, nodeorder from workflow_flownode where workflowid=" + workflow.id);
            while(rs.next()) {
                String nodeid = Util.null2String(rs.getString("nodeid"));
                String nodeorder = Util.null2String(rs.getString("nodeorder"));
                nodeorderMap.put(nodeid, nodeorder);
            }
            // TD100149 end
//            int newNodeorder = 1; // 标示新增节点顺序，从0开始
            int oldNodeorder = 1; // 标示已有节点顺序，从1开始，用于处理已有节点顺序为空的情况

            // TD100149 begin -- 根据workflowid获取已有的出口id和出口顺序的映射
            Map linkorderMap = new HashMap();
            rs.executeSql("select id, linkorder from workflow_nodelink where workflowid=" + workflow.id + " order by linkorder, nodeid, id");
            while(rs.next()) {
                String id = Util.null2String(rs.getString("id"));
                String linkorder = Util.null2String(rs.getString("linkorder"));
                linkorderMap.put(id, linkorder);
            }
            // TD100149 end
//            int newLinkorder = 1; // 标示新增出口顺序，从0开始
            int oldLinkorder = 1; // 标示已有出口顺序，从1开始，用于处理已有出口顺序为空的情况

            Map<Integer, WorkflowNode> nodeMap = new HashMap<>();
            List<String> isMustPassLinkXmlIds = new ArrayList<>();//遍历节点时，记录分叉合并点必须通过的路径在xml上的id(不是路径id)

//            int maxNodeOrder = 0;
//            int maxLinkOrder = 0;
//            rs.executeQuery("select max(nodeorder) as maxOrder from workflow_flownode where workflowid = ?", workflowId);
//            if (rs.next()) {
//                maxNodeOrder = Util.getIntValue(rs.getString("maxOrder"), 0);
//            }
//            rs.executeQuery("select max(linkorder) as maxorder from workflow_nodelink where workflowid = ?", workflowId);
//            if (rs.next()) {
//                maxLinkOrder = Util.getIntValue(rs.getString("maxOrder"), 0);
//            }


            //先遍历出所有的节点，存在nodeMap中，遍历出口时可以直接取对应关系
            for (Element element : mxCells) {
                if(!"1".equals(element.attributeValue(XML_ATTRIBUTE_EDGE))
                        && !"1".equals(element.attributeValue(XML_ATTRIBUTE_ISGROUPAREA)) && !"1".equals(element.attributeValue(XML_ATTRIBUTE_ISHELPFULTEXT))){
                    /**创建流程节点*/
                    WorkflowNode workflowNode = new WorkflowNode();

                    int id = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_ID),0);

                    if (id == 0 || id == 1) {//id为0和1时，是前端传过来的xml的固定element，不存放数据，过滤掉
                        continue;
                    }

                    workflowNode.id = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_NODEID),0);
                    workflowNode.name  = Util.null2String(element.attributeValue(XML_ATTRIBUTE_VALUE));
                    workflowNode.nodeType = Util.null2String(element.attributeValue(XML_ATTRIBUTE_NODETYPE));
                    if("".equals(workflowNode.nodeType)) {
                        workflowNode.nodeType = Util.null2String(element.attributeValue("nodetype"));
                    }
                    String isreject = workflowNode.nodeType.equals("1")?"1":"0";
                    //存储节点处理的属性 by cyril
                    //System.out.println("nodename:"+workflowNode.name);
                    workflowNode.attrMap.put("nodename", workflowNode.name);//流程名称
                    String nodeAttribute = Util.null2String(element.attributeValue(XML_ATTRIBUTE_NODEATTRIBUTE));
                    if(!nodeAttribute.equals("")){
                        workflowNode.attrMap.put("nodeattribute",nodeAttribute);//节点属性
                        workflowNode.setNodeAttribute(nodeAttribute);
                    }
                    else{
                        workflowNode.attrMap.put("nodeattribute","0");//节点属性
                        workflowNode.setNodeAttribute("0");
                    }
                    workflowNode.setStyle(Util.null2String(element.attributeValue(XML_ATTRIBUTE_STYLE)));
                    workflowNode.attrMap.put("drawStyle", workflowNode.getStyle());
                    workflowNode.attrMap.put("nodeattribute",nodeAttribute);//节点属性
                    int passNum = 0;
                    if ("3".equals(nodeAttribute)) {//通过分支数合并
                        passNum = Util.getIntValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_PASSBRANCHNUM)), 0);
                    } else if("4".equals(nodeAttribute)){//指定分支合并
                        String[] xmlIds = Util.null2String(element.attributeValue(XML_ATTRIBUTE_TARGETBRANCHVALUE)).split(",");
                        for (String xmlId : xmlIds) {
                            isMustPassLinkXmlIds.add(xmlId);
                        }
                    } else if ("5".equals(nodeAttribute)) {//比例合并
                        passNum = Util.getIntValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_PROPORTMERGE)), 0);
                    }
                    workflowNode.attrMap.put("passnum", passNum);//通过的分支数量
                    workflowNode.attrMap.put("isreject", isreject);//节点是否可退回

                    /**获取节点图形化信息*/
                    Element geometry = element.element(XML_ELEMENT_MX_GEOMETRY);

                    workflowNode.x = (int)Util.getDoubleValue(Util.null2String(geometry.attributeValue(XML_ATTRIBUTE_X)));//横坐标
                    workflowNode.y = (int)Util.getDoubleValue(Util.null2String(geometry.attributeValue(XML_ATTRIBUTE_Y)));//纵坐标


                    //System.out.println("x="+workflowNode.x+" y="+workflowNode.y+" test="+vml.getAttribute("shapetype"));
                    if(workflowNode.id == 0){//没有nodeid，表示是新节点

                        // 如果是新节点，节点顺序从mxCells.size()开始
                        workflowNode.setNodeorder(Util.getIntValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_ORDER))));
//                        newNodeorder++;

                        String tmpid = DesignOperationBiz.addWorkflowNode(workflowId, delNodeIds, remoteAddr, user, workflowNode);
                        if(Util.getIntValue(tmpid) <= 0){
                            continue;
                        }
                        workflowNode.id = Util.getIntValue(tmpid);
                        tmpList.put(workflowNode.id+"", tmpid);
                        //已经处理过删除节点的操作，清除。
                        delNodeIds="";
                    }else { // 如果是老节点
                        String nodeorder = (String) nodeorderMap.get("" + workflowNode.id);
                        if("".equals(nodeorder)) {
                            nodeorder = "" + oldNodeorder;
                        }
                        workflowNode.setNodeorder(Util.getIntValue(nodeorder));
                        oldNodeorder++;
                    }
                    /**组装流程节点信息*/
                    workflow.addNode(workflowNode);
                    nodeMap.put(id, workflowNode);
                }
            }

            /**获取业务组**/
            List groups = new ArrayList();

            for (Element element : mxCells) {
                //此属性为1，表示为路径
                if("1".equals(element.attributeValue(XML_ATTRIBUTE_EDGE))) {

                    int xmlId = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_ID), -1);
                    /**创建流程出口*/
                    WorkflowLine workflowLine = new WorkflowLine();
                    /**获取出口基本信息*/
                    workflowLine.id = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_LINKID), -1);

                    int source = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_SOURCE));
                    int target = Util.getIntValue(element.attributeValue(XML_ATTRIBUTE_TARGET));

                    int fromNodeId = nodeMap.get(source) != null ? nodeMap.get(source).getId() : -1;
                    workflowLine.fromNodeId = fromNodeId;
                    workflowLine.toNodeId = nodeMap.get(target) != null ? nodeMap.get(target).getId() : -1;

                    workflowLine.setLineName(Util.null2String(element.attributeValue(XML_ATTRIBUTE_TEXT)));
                    workflowLine.setRemindMsg(Util.null2String(element.attributeValue(XML_ATTRIBUTE_EXITINFO)));
                    workflowLine.setIsBuildCodeString(Util.null2String(element.attributeValue(XML_ATTRIBUTE_ISBUILDCODE)));
                    workflowLine.setIsMustpass((isMustPassLinkXmlIds.indexOf(xmlId+"") > -1 || isMustPassLinkXmlIds.indexOf("link_" + workflowLine.id) > -1) ? "1" : "0");

                    String isreject = Util.null2String(element.attributeValue(XML_ATTRIBUTE_ISREJECT));
                    rs.executeQuery("select * from workflow_nodebase where id = ?",fromNodeId);
                    if (rs.next()) {
                        String tmpisreject = rs.getString("isreject");
                        if(!"1".equals(tmpisreject)){
                            isreject = "0";
                        }
                    }
                    workflowLine.setIsReject(isreject);
                    String remindMsg = Util.null2String(element.attributeValue(XML_ATTRIBUTE_EXITINFO));
                    if(remindMsg.startsWith("base64_")) {
                        BASE64Decoder base64decoder = new BASE64Decoder();
                        remindMsg = new String(base64decoder.decodeBuffer(remindMsg.substring("base64_".length())), "UTF-8");
                    }
                    workflowLine.setRemindMsg(remindMsg);

                    Element geometryElement = element.element(XML_ELEMENT_MX_GEOMETRY);
                    Element arrayElement = geometryElement.element(XML_ELEMENT_ARRAY);
                    String newPoints = "";
                    if(arrayElement != null) {
                        List<Element> points = arrayElement.elements(XML_ELEMENT_MX_POINT);
                        for (Element point : points) {
                            String xPoint = point.attributeValue(XML_ATTRIBUTE_X);
                            String yPoint = point.attributeValue(XML_ATTRIBUTE_Y);
                            newPoints += xPoint + "," + yPoint + ",";
                        }
                        if (newPoints.length() > 1) {
                            newPoints = newPoints.substring(0, newPoints.length() - 1);
                        }
                    }
                    workflowLine.setNewPoints(newPoints);
                    workflowLine.attrMap.put("e9points", newPoints);
                    /**
                     * 新老数据转换规则
                     * 老           新
                     * 0    --->   x = 0.5  y = 1
                     *
                     * 90   --->   x = 0    y = 0.5
                     *
                     * 180  --->   x = 0.5  y = 0
                     *
                     * -90  --->   x = 1   y = 0.5
                     */
                    String style = Util.null2String(element.attributeValue(XML_ATTRIBUTE_STYLE));
                    Map<String, String> styleMap = DesignUtil.parserStrToMap(style);
                    workflowLine.setStyle(style);
                    workflowLine.attrMap.put("drawStyle", style);
                    workflowLine.attrMap.put("linkname", workflowLine.getLineName());//出口名称
                    workflowLine.attrMap.put("tipsinfo", workflowLine.getRemindMsg());//出口提示信息
                    workflowLine.attrMap.put("nodeid",workflowLine.fromNodeId+"");//起始节点
                    workflowLine.attrMap.put("destnodeid",workflowLine.toNodeId+"");//目标节点
                    if(!"".equals(workflowLine.getIsBuildCodeString())) {
                        workflowLine.attrMap.put("isBulidCode", workflowLine.getIsBuildCodeString());//是否生成编号
                    }
                    workflowLine.attrMap.put("isreject", workflowLine.getIsReject());//是否可退回
                    workflowLine.attrMap.put("ismustpass", workflowLine.getIsMustpass());//是否必须通过
                    workflowLine.attrMap.put("tipsinfo", workflowLine.getRemindMsg());//出口提示信息

                    if(workflowLine.id <= 0){
                        // 如果是新出口，出口顺序从stepList.size()开始
                        workflowLine.setLinkorder(Util.getIntValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_ORDER))));
//                        newLinkorder++;

                        String tmpLinkId = DesignOperationBiz.addWorkflowLink(workflowId,this.delStepIds, remoteAddr, user, workflowLine);
                        workflowLine.id = Util.getIntValue(tmpLinkId);
                        //已经处理过删除出口的操作，清除。
                        this.delStepIds ="";
                    }else { // 如果是老出口
                        String linkorder = (String) linkorderMap.get("" + workflowLine.id);
                        if("".equals(linkorder)) {
                            linkorder = "" + oldLinkorder;
                        }
                        workflowLine.setLinkorder(Util.getIntValue(linkorder));
                        oldLinkorder++;
                    }
                    workflowLine.attrMap.put("linkorder", workflowLine.getLinkorder()); // 出口顺序
//
//                    /**组装流程出口信息*/
                    workflow.addLine(workflowLine);
                } else if ("1".equals(element.attributeValue(XML_ATTRIBUTE_ISGROUPAREA))) {
                    WorkflowGroup wg = new WorkflowGroup();
                    wg.setWorkflowid(workflow.id);
                    wg.setGroupname(element.attributeValue(XML_ATTRIBUTE_VALUE));
                    wg.setDirection(0);

                    Element geometry = element.element(XML_ELEMENT_MX_GEOMETRY);

                    wg.setX(Double.parseDouble(geometry.attributeValue(XML_ATTRIBUTE_X)));
                    wg.setY(Double.parseDouble(geometry.attributeValue(XML_ATTRIBUTE_Y)));
                    wg.setWidth(Double.parseDouble(geometry.attributeValue(XML_ATTRIBUTE_WIDTH)));
                    wg.setHeight(Double.parseDouble(geometry.attributeValue(XML_ATTRIBUTE_HEIGHT)));
                    wg.setNew(true);
                    groups.add(wg);
                } else if("1".equals(element.attributeValue(XML_ATTRIBUTE_ISHELPFULTEXT))) {//说明文字
                    TextInfo textInfo = new TextInfo();
                    //文本将换行符替换回去
//                    textInfo.setTextValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_VALUE).replace("_#10_", "&#10;")));
                    textInfo.setTextValue(Util.null2String(element.attributeValue(XML_ATTRIBUTE_VALUE).replace("\n", "&#10;")));
                    Element geometry = element.element(XML_ELEMENT_MX_GEOMETRY);
                    textInfo.setxPoint(geometry.attributeValue(XML_ATTRIBUTE_X));
                    textInfo.setyPoint(geometry.attributeValue(XML_ATTRIBUTE_Y));
                    textInfo.setHeight(geometry.attributeValue(XML_ATTRIBUTE_HEIGHT));
                    textInfo.setWidth(geometry.attributeValue(XML_ATTRIBUTE_WIDTH));
                    textInfo.setWorkflowId(workflow.getId());
                    workflow.addHelpText(textInfo);
                }
            }

            //横纵向分组
            if(!"".equals(this.groupsJsonStr)) {
                JSONObject groupObject = JSONObject.parseObject(groupsJsonStr);
                JSONArray rows = groupObject.getJSONArray("row");
                JSONArray cols = groupObject.getJSONArray("col");

                for (int i = 0; i < rows.size(); i++) {//横向分组
                    JSONObject rowGroup = rows.getJSONObject(i);
                    WorkflowGroup wg = new WorkflowGroup();

                    wg.setWorkflowid(workflow.id);
                    wg.setGroupname(rowGroup.getString("value"));
                    wg.setDirection(1);

                    JSONObject position = rowGroup.getJSONObject("position");
                    double x = Util.getDoubleValue(position.getString("left"), 0);
                    double y = Util.getDoubleValue(position.getString("top"), 0);
                    double panelWidth = Util.getDoubleValue(rowGroup.getString("panelWidth"), 0);
                    y = y - panelWidth;


                    wg.setX(x);
                    wg.setY(y);
                    wg.setWidth(0);
                    wg.setHeight(panelWidth);
                    wg.setNew(true);
                    groups.add(wg);
                }

                for (int i = 0; i < cols.size(); i++) {//纵向分组
                    JSONObject colGroup = cols.getJSONObject(i);
                    WorkflowGroup wg = new WorkflowGroup();

                    wg.setWorkflowid(workflow.id);
                    wg.setGroupname(colGroup.getString("value"));
                    wg.setDirection(2);

                    JSONObject position = colGroup.getJSONObject("position");
                    double x = Util.getDoubleValue(position.getString("left"), 0);
                    double y = Util.getDoubleValue(position.getString("top"), 0);
                    double panelWidth = Util.getDoubleValue(colGroup.getString("panelWidth"), 0);
                    x = x - panelWidth;


                    wg.setX(x);
                    wg.setY(y);
                    wg.setWidth(panelWidth);
                    wg.setHeight(0);
                    wg.setNew(true);
                    groups.add(wg);
                }

            }
            workflow.setGroups(groups);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return workflow;
    }

    /**
     * 改变style中的颜色
     * @param style
     * @param colorAttribute
     * @param colorStr
     */
    protected String changeColor(String style, String colorAttribute, String colorStr) {
        int indexMark = style.indexOf(colorAttribute);
        if(indexMark != -1) {
            String tempStr1 = style.substring(0, indexMark);
            String tempStr2 = style.substring(indexMark + colorAttribute.length() + 8);
            style = tempStr1 + tempStr2;
        }
        style += colorAttribute + "=" + colorStr + ";";
        return style;
    }

    public List<Map<String, Object>> parseResourceInfo(List<String> list) {
        List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();
        String splitstring = "_#WFSPSTR_OPTTP#_";
        String agentSplitString = "->";
        RecordSet rslog = new RecordSet();
        try {
            Iterator<String> it = list.iterator();
            while (it.hasNext()) {
                String operatorInfo =Util.null2String(it.next());
                String[] operatorInfoArray = operatorInfo.split(agentSplitString);
                String[] opratorArrya = operatorInfoArray[0].split(splitstring);
                Map<String, Object> omap = new HashMap<String, Object>();
                omap.put("type", Util.getIntValue(opratorArrya[0]));
                omap.put("id", Util.getIntValue(opratorArrya[1]));

                omap.put("name", opratorArrya[2]);
                if (operatorInfoArray.length > 1) {
                    omap.put("hasAgent", true);
                    opratorArrya = operatorInfoArray[1].split(splitstring);
                    Map<String, Object> agentMap = new HashMap<String, Object>();
                    agentMap.put("type", Util.getIntValue(opratorArrya[0]));
                    agentMap.put("id", Util.getIntValue(opratorArrya[1]));
                    agentMap.put("name", opratorArrya[2]);
                    omap.put("agent", agentMap);

                }
                result.add(omap);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取连接点方向
     */
    public String getDirection(int index, String type) {
        switch (index) {
            case 0: return getDirection("1", "0.5", type);
            case 1: return getDirection("1", "0.75", type);
            case 2: return getDirection("1", "1", type);
            case 3: return getDirection("0.75", "1", type);
            case 4: return getDirection("0.5", "1", type);
            case 5: return getDirection("0.25", "1", type);
            case 6: return getDirection("0", "1", type);
            case 7: return getDirection("0", "0.75", type);
            case 8: return getDirection("0", "0.5", type);
            case 9: return getDirection("0", "0.25", type);
            case 10: return getDirection("0", "0", type);
            case 11: return getDirection("0.25", "0", type);
            case 12: return getDirection("0.5", "0", type);
            case 13: return getDirection("0.75", "0", type);
            case 14: return getDirection("1", "0", type);
            case 15: return getDirection("1", "0.25", type);
            default: return getDirection("1", "0.5", type);
        }
    }

    public String getDirection(String x, String y, String type) {
        return type + "X=" + x + ";" + type + "Y=" + y + ";";
    }

    /**
     * 计算连接点位置， 防止有多条线条时重合
     * @param workflow
     */
    private void calcuLinkDirection(Workflow workflow) {
        Map<String, List<WorkflowLine>> nodeLineMap = new LinkedHashMap<>();

        for (int i = 0; i < workflow.lines.size(); i++) {
            WorkflowLine workflowLine = (WorkflowLine)workflow.lines.get(i);
            if(!"".equals(workflowLine.getStyle())) {
                nodeLineMap = new LinkedHashMap<>();
                break;
            }
            int fromNodeId = workflowLine.getFromNodeId();
            int toNodeId = workflowLine.getToNodeId();
            int exitDirection = workflowLine.getStartDirection();
            int entryDirection = workflowLine.getEndDirection();

            List<WorkflowLine> exitList = nodeLineMap.get(fromNodeId + "_" + exitDirection);
            if (exitList == null) {
                exitList = new ArrayList<>();
            }
            exitList.add(workflowLine);
            nodeLineMap.put(fromNodeId + "_" + exitDirection, exitList);


            List<WorkflowLine> entryList = nodeLineMap.get(toNodeId + "_" + entryDirection);
            if (entryList == null) {
                entryList = new ArrayList<>();
            }
            entryList.add(workflowLine);
            nodeLineMap.put(toNodeId + "_" + entryDirection, entryList);
        }


        for(String key : nodeLineMap.keySet()) {
            List<WorkflowLine> list = nodeLineMap.get(key);
            if (list != null && list.size() > 1 && key != null && key.indexOf("_") > -1) {
                int size = list.size();
                double distance = 0.25 / size;
                int nodeId = Util.getIntValue(key.split("_")[0]);
                int direction = Util.getIntValue(key.split("_")[1]);
                for (int i = 0; i < size; i++) {
                    WorkflowLine lineEntity = list.get(i);
                    boolean isEntry = nodeId == lineEntity.getToNodeId();
                    double x = isEntry ? lineEntity.getEntryX() : lineEntity.getExitX();
                    double y = isEntry ? lineEntity.getEntryY() : lineEntity.getExitY();
                    if(direction == 0 || direction == 180) {
                        if(i % 2 > 0) {
                            x += distance * (i + 1);
                        } else {
                            x -= distance * (i + 1);
                        }
                    } else if(direction == 90 || direction == -90) {
                        if(i % 2 > 0) {
                            y += distance * (i + 1);
                        } else {
                            y -= distance * (i + 1);
                        }
                    }
                    if (isEntry) {
                        lineEntity.setEntryX(x);
                        lineEntity.setEntryY(y);
                    } else {
                        lineEntity.setExitX(x);
                        lineEntity.setExitY(y);
                    }
                }
            }
        }
    }

    //过滤偏差较小的连接点
    private void filterLinkPoint(WorkflowLine workflowLine) {

//        if (workflowLine.getId() != 640) {
//            return;
//        }

        String pointStr = workflowLine.getNewPoints();
        String newPointStr = "";
        double mark = 9;
        if (pointStr != null && pointStr.length() > 0) {
            String[] points = pointStr.split(",");
            if(points.length <= 2) return;

            newPointStr += "," + points[0] + "," + points[1];

            for (int i = 2; i <= points.length - 2; i = i+2) {

                double beforeX = Util.getDoubleValue(points[i - 2]);
                double beforeY = Util.getDoubleValue(points[i - 1]);

                double currentX = Util.getDoubleValue(points[i]);
                double currentY = Util.getDoubleValue(points[i + 1]);

                if (Math.abs(beforeX - currentX) > mark || Math.abs(beforeY - currentY) > mark) {
                    if(Math.abs(beforeX - currentX) <= mark) {
                        currentX = beforeX;
                        points[i] = beforeX+"";
                    }
                    if(Math.abs(beforeY - currentY) <= mark) {
                        currentY = beforeY;
                        points[i + 1] = beforeY+"";
                    }
                    newPointStr += "," + currentX + "," + currentY;
                } else {//x和y都未满足偏移量的点，过滤掉，在数组中设置成和上一个点一样
                    points[i] = beforeX+"";
                    points[i + 1] = beforeY+"";
                }
            }
        }
        if(!newPointStr.equals("")) {
            newPointStr = newPointStr.substring(1);
        }
        workflowLine.setNewPoints(newPointStr);
    }

    private String appendDirectionStyle(String style, WorkflowLine workflowLine, Map<Integer, WorkflowNode> nodeMap) {

        /** 出去 **/
        if (workflowLine.getExitX() == 0.5) {//上下两个方向，改exitX
            WorkflowNode node = nodeMap.get(workflowLine.getFromNodeId());
            int nodeX = node.x + 30;
            int nodeWidth = node.getWidth();
            String[] linePoints = workflowLine.getNewPoints().split(",");
            if (linePoints.length > 2) {
                double pointX = Util.getDoubleValue(linePoints[0]) + 20;

                double finalExitX = (pointX-nodeX) * 1.0 / nodeWidth;

                style += "exitX="+finalExitX+";exitY="+workflowLine.getExitY()+";";
            } else {
                style += "exitX="+workflowLine.getExitX()+";exitY="+workflowLine.getExitY()+";";
            }
        }else if(workflowLine.getExitY() == 0.5) {//左右两个方向，改exitY
            WorkflowNode node = nodeMap.get(workflowLine.getFromNodeId());
            int nodeY = node.y + 30;
            int nodeHeight = node.getHeight();
            String[] linePoints = workflowLine.getNewPoints().split(",");
            if (linePoints.length > 2) {
                double pointY = Util.getDoubleValue(linePoints[1]) + 20;

                double finalExitY = (pointY-nodeY) * 1.0 / nodeHeight;

                style += "exitX="+workflowLine.getExitX()+";exitY="+finalExitY+";";
            } else {
                style += "exitX="+workflowLine.getExitX()+";exitY="+workflowLine.getExitY()+";";
            }
        } else {
            style += "exitX="+workflowLine.getExitX()+";exitY="+workflowLine.getExitY()+";";
        }



        /** 进入 **/
        if (workflowLine.getEntryX() == 0.5) {//上下两个方向，改entryX
            WorkflowNode entryNode = nodeMap.get(workflowLine.getToNodeId());
            int entryNodeX = entryNode.x + 30;
            int entryWidth = entryNode.getWidth();
            String linePointStr = workflowLine.getNewPoints();
            String[] linePoints = linePointStr.split(",");
            if (linePoints.length > 2) {
                double entryX = Util.getDoubleValue(linePoints[linePoints.length - 2]) + 20;

                double finalEntryX = (entryX-entryNodeX) * 1.0 / entryWidth;

                style += "entryX="+finalEntryX+";entryY="+workflowLine.getEntryY()+";";
            } else {
                style += "entryX="+workflowLine.getEntryX()+";entryY="+workflowLine.getEntryY()+";";
            }
        } else if(workflowLine.getEntryY() == 0.5) {//左右两个方向， 改entryY
            WorkflowNode node = nodeMap.get(workflowLine.getToNodeId());
            int nodeY = node.y + 30;
            int nodeHeight = node.getHeight();
            String[] linePoints = workflowLine.getNewPoints().split(",");
            if (linePoints.length > 2) {
                double pointY = Util.getDoubleValue(linePoints[linePoints.length - 1]) + 20;

                double finalEntryY = (pointY-nodeY) * 1.0 / nodeHeight;

                style += "entryX="+workflowLine.getEntryX()+";entryY="+finalEntryY+";";
            } else {
                style += "entryX="+workflowLine.getEntryX()+";entryY="+workflowLine.getEntryY()+";";
            }
        } else {
            style += "entryX="+workflowLine.getEntryX()+";entryY="+workflowLine.getEntryY()+";";
        }
        return style;
    }

    public String filterStyle(String style, WorkflowNode node) {


        try {
            int index1 = style.indexOf("{");
            int index2 = style.indexOf("}");
            if (index1 != -1 && index2 != -1) {

                String icons = style.substring(index1 + 1, index2);

                String oldIcons = new String(icons);

                icons = icons.replace("\"beforeNode\":\"icon-workflow-caozuoqian\"", "");
                icons = icons.replace("\"nodeAfter\":\"icon-workflow-caozuohou\"", "");

                String[] iconArray = icons.split(",");

                String newIcon = "";
                for (int i = 0; i < iconArray.length; i++) {
                    if (!"".equals(iconArray[i])) {
                        newIcon += "," + iconArray[i];
                    }
                }
                if (newIcon.length() > 0) {
                    newIcon = newIcon.substring(1);
                }

                if (node.isHasNodeBefAddOpr()) {//节点前附加操作
                    if ("".equals(newIcon)) {
                        newIcon += "\"beforeNode\":\"icon-workflow-caozuoqian\"";
                    } else {
                        newIcon += ",\"beforeNode\":\"icon-workflow-caozuoqian\"";
                    }
                }

                if (node.isHasNodeAftAddOpr()) {//节点后附加操作
                    if ("".equals(newIcon)) {
                        newIcon += "\"nodeAfter\":\"icon-workflow-caozuohou\"";
                    } else {
                        newIcon += ",\"nodeAfter\":\"icon-workflow-caozuohou\"";
                    }
                }

                if (oldIcons != null && oldIcons.trim().length() > 0) {
                    style = style.replace(oldIcons, newIcon);
                } else {
                    style = style.substring(0, index1+1) + newIcon + style.substring(index2);
                }

            } else if (node.isHasNodeAftAddOpr() || node.isHasNodeBefAddOpr()) {
                String newIcon = "";

                if (node.isHasNodeBefAddOpr()) {//节点前附加操作
                    if ("".equals(newIcon)) {
                        newIcon += "\"beforeNode\":\"icon-workflow-caozuoqian\"";
                    } else {
                        newIcon += ",\"beforeNode\":\"icon-workflow-caozuoqian\"";
                    }
                }

                if (node.isHasNodeAftAddOpr()) {//节点后附加操作
                    if ("".equals(newIcon)) {
                        newIcon += "\"nodeAfter\":\"icon-workflow-caozuohou\"";
                    } else {
                        newIcon += ",\"nodeAfter\":\"icon-workflow-caozuohou\"";
                    }
                }

                style += "icons={" + newIcon + "};";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return style;
    }

    /**
     * 获取自动跳过的节点id
     * @param requestId
     * @return
     */
    public List<Integer> getAutoPassedNodeIds(int requestId) {
        RecordSet rs = new RecordSet();
        List<Integer> autoPassedNodeIds = new ArrayList<>();

        //异常处理跳过
        rs.executeQuery("select passedNodes from workflow_requestexception where requestid = ?", requestId);
        while (rs.next()) {
            String tempIds = Util.null2String(rs.getString(1));
            if (tempIds.indexOf(",") > -1) {
                String[] idArray = tempIds.split(",");
                for (String id : idArray) {
                    autoPassedNodeIds.add(Util.getIntValue(id));
                }
            } else {
                autoPassedNodeIds.add(Util.getIntValue(tempIds));
            }
        }
        return autoPassedNodeIds;
    }


}
